home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / tiff / tif_write.c < prev    next >
C/C++ Source or Header  |  1995-06-21  |  18KB  |  570 lines

  1. /* $Header: /usr/people/sam/tiff/libtiff/RCS/tif_write.c,v 1.60 1994/09/17 23:22:37 sam Exp $ */
  2.  
  3. /*
  4.  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 Sam Leffler
  5.  * Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26.  
  27. /*
  28.  * TIFF Library.
  29.  *
  30.  * Scanline-oriented Write Support
  31.  */
  32. #include "tiffiop.h"
  33. #include <assert.h>
  34. #include <stdio.h>
  35.  
  36. #define    STRIPINCR    20        /* expansion factor on strip array */
  37.  
  38. static    int TIFFWriteCheck(TIFF*, int, const char*);
  39. static    int TIFFBufferSetup(TIFF*, const char*);
  40. static    int TIFFGrowStrips(TIFF*, int, const char*);
  41. static    int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t);
  42. static    int TIFFSetupStrips(TIFF*);
  43.  
  44. int
  45. TIFFWriteScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample)
  46. {
  47.     static const char module[] = "TIFFWriteScanline";
  48.     register TIFFDirectory *td;
  49.     int status, imagegrew = 0;
  50.     tstrip_t strip;
  51.  
  52.     if (!TIFFWriteCheck(tif, 0, module))
  53.         return (-1);
  54.     /*
  55.      * Handle delayed allocation of data buffer.  This
  56.      * permits it to be sized more intelligently (using
  57.      * directory information).
  58.      */
  59.     if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) {
  60.         if (!TIFFBufferSetup(tif, module))
  61.             return (-1);
  62.         tif->tif_flags |= TIFF_BUFFERSETUP;
  63.     }
  64.     td = &tif->tif_dir;
  65.     /*
  66.      * Extend image length if needed
  67.      * (but only for PlanarConfig=1).
  68.      */
  69.     if (row >= td->td_imagelength) {    /* extend image */
  70.         if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
  71.             TIFFError(tif->tif_name,
  72.         "Can not change \"ImageLength\" when using separate planes");
  73.             return (-1);
  74.         }
  75.         td->td_imagelength = row+1;
  76.         imagegrew = 1;
  77.     }
  78.     /*
  79.      * Calculate strip and check for crossings.
  80.      */
  81.     if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
  82.         if (sample >= td->td_samplesperpixel) {
  83.             TIFFError(tif->tif_name,
  84.                 "%d: Sample out of range, max %d",
  85.                 sample, td->td_samplesperpixel);
  86.             return (-1);
  87.         }
  88.         strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
  89.     } else
  90.         strip = row / td->td_rowsperstrip;
  91.     if (strip != tif->tif_curstrip) {
  92.         /*
  93.          * Changing strips -- flush any data present.
  94.          */
  95.         if (!TIFFFlushData(tif))
  96.             return (-1);
  97.         tif->tif_curstrip = strip;
  98.         /*
  99.          * Watch out for a growing image.  The value of
  100.          * strips/image will initially be 1 (since it
  101.          * can't be deduced until the imagelength is known).
  102.          */
  103.         if (strip >= td->td_stripsperimage && imagegrew)
  104.             td->td_stripsperimage =
  105.                 howmany(td->td_imagelength, td->td_rowsperstrip);
  106.         tif->tif_row =
  107.             (strip % td->td_stripsperimage) * td->td_rowsperstrip;
  108.         if (tif->tif_preencode && !(*tif->tif_preencode)(tif))
  109.             return (-1);
  110.         tif->tif_flags |= TIFF_POSTENCODE;
  111.     }
  112.     /*
  113.      * Check strip array to make sure there's space.
  114.      * We don't support dynamically growing files that
  115.      * have data organized in separate bitplanes because
  116.      * it's too painful.  In that case we require that
  117.      * the imagelength be set properly before the first
  118.      * write (so that the strips array will be fully
  119.      * allocated above).
  120.      */
  121.     if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
  122.         return (-1);
  123.     /*
  124.      * Ensure the write is either sequential or at the
  125.      * beginning of a strip (or that we can randomly
  126.      * access the data -- i.e. no encoding).
  127.      */
  128.     if (row != tif->tif_row) {
  129.         if (tif->tif_seek) {
  130.             if (row < tif->tif_row) {
  131.                 /*
  132.                  * Moving backwards within the same strip:
  133.                  * backup to the start and then decode
  134.                  * forward (below).
  135.                  */
  136.                 tif->tif_row = (strip % td->td_stripsperimage) *
  137.                     td->td_rowsperstrip;
  138.                 tif->tif_rawcp = tif->tif_rawdata;
  139.             }
  140.             /*
  141.              * Seek forward to the desired row.
  142.              */
  143.             if (!(*tif->tif_seek)(tif, row - tif->tif_row))
  144.                 return (-1);
  145.             tif->tif_row = row;
  146.         } else {
  147.             TIFFError(tif->tif_name,
  148.             "Compression algorithm does not support random access");
  149.             return (-1);
  150.         }
  151.     }
  152.     status = (*tif->tif_encoderow)(tif, (tidata_t) buf,
  153.         tif->tif_scanlinesize, sample);
  154.     tif->tif_row++;
  155.     return (status);
  156. }
  157.  
  158. /*
  159.  * Encode the supplied data and write it to the
  160.  * specified strip.  There must be space for the
  161.  * data; we don't check if strips overlap!
  162.  *
  163.  * NB: Image length must be setup before writing; this
  164.  *     interface does not support automatically growing
  165.  *     the image on each write (as TIFFWriteScanline does).
  166.  */
  167. tsize_t
  168. TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
  169. {
  170.     static const char module[] = "TIFFWriteEncodedStrip";
  171.     TIFFDirectory *td = &tif->tif_dir;
  172.  
  173.     if (!TIFFWriteCheck(tif, 0, module))
  174.         return ((tsize_t) -1);
  175.     if (strip >= td->td_nstrips) {
  176.         TIFFError(module, "%s: Strip %lu out of range, max %lu",
  177.             tif->tif_name, (u_long) strip, (u_long) td->td_nstrips);
  178.         return ((tsize_t) -1);
  179.     }
  180.     /*
  181.      * Handle delayed allocation of data buffer.  This
  182.      * permits it to be sized according to the directory
  183.      * info.
  184.      */
  185.     if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) {
  186.         if (!TIFFBufferSetup(tif, module))
  187.             return ((tsize_t) -1);
  188.         tif->tif_flags |= TIFF_BUFFERSETUP;
  189.     }
  190.     tif->tif_curstrip = strip;
  191.     tif->tif_flags &= ~TIFF_POSTENCODE;
  192.     if (tif->tif_preencode && !(*tif->tif_preencode)(tif))
  193.         return ((tsize_t) -1);
  194.     if (!(*tif->tif_encodestrip)(tif,
  195.         (tidata_t) data, cc, (tsample_t)(strip / td->td_stripsperimage)))
  196.         return ((tsize_t) 0);
  197.     if (tif->tif_postencode && !(*tif->tif_postencode)(tif))
  198.         return (-1);
  199.     if (td->td_fillorder != tif->tif_fillorder &&
  200.         (tif->tif_flags & TIFF_NOBITREV) == 0)
  201.         TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
  202.     if (tif->tif_rawcc > 0 &&
  203.         !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
  204.         return (-1);
  205.     tif->tif_rawcc = 0;
  206.     tif->tif_rawcp = tif->tif_rawdata;
  207.     return (cc);
  208. }
  209.  
  210. /*
  211.  * Write the supplied data to the specified strip.
  212.  * There must be space for the data; we don't check
  213.  * if strips overlap!
  214.  *
  215.  * NB: Image length must be setup before writing; this
  216.  *     interface does not support automatically growing
  217.  *     the image on each write (as TIFFWriteScanline does).
  218.  */
  219. tsize_t
  220. TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
  221. {
  222.     static const char module[] = "TIFFWriteRawStrip";
  223.  
  224.     if (!TIFFWriteCheck(tif, 0, module))
  225.         return ((tsize_t) -1);
  226.     if (strip >= tif->tif_dir.td_nstrips) {
  227.         TIFFError(module, "%s: Strip %lu out of range, max %lu",
  228.             tif->tif_name, (u_long) strip,
  229.             (u_long) tif->tif_dir.td_nstrips);
  230.         return ((tsize_t) -1);
  231.     }
  232.     return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ?
  233.         cc : (tsize_t) -1);
  234. }
  235.  
  236. /*
  237.  * Write and compress a tile of data.  The
  238.  * tile is selected by the (x,y,z,s) coordinates.
  239.  */
  240. tsize_t
  241. TIFFWriteTile(TIFF* tif,
  242.     tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
  243. {
  244.     if (!TIFFCheckTile(tif, x, y, z, s))
  245.         return (-1);
  246.     /*
  247.      * NB: A tile size of -1 is used instead of tif_tilesize knowing
  248.      *     that TIFFWriteEncodedTile will clamp this to the tile size.
  249.      *     This is done because the tile size may not be defined until
  250.      *     after the output buffer is setup in TIFFBufferSetup.
  251.      */
  252.     return (TIFFWriteEncodedTile(tif,
  253.         TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
  254. }
  255.  
  256. /*
  257.  * Encode the supplied data and write it to the
  258.  * specified tile.  There must be space for the
  259.  * data.  The function clamps individual writes
  260.  * to a tile to the tile size, but does not (and
  261.  * can not) check that multiple writes to the same
  262.  * tile do not write more than tile size data.
  263.  *
  264.  * NB: Image length must be setup before writing; this
  265.  *     interface does not support automatically growing
  266.  *     the image on each write (as TIFFWriteScanline does).
  267.  */
  268. tsize_t
  269. TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
  270. {
  271.     static const char module[] = "TIFFWriteEncodedTile";
  272.     TIFFDirectory *td;
  273.  
  274.     if (!TIFFWriteCheck(tif, 1, module))
  275.         return ((tsize_t) -1);
  276.     td = &tif->tif_dir;
  277.     if (tile >= td->td_nstrips) {
  278.         TIFFError(module, "%s: Tile %lu out of range, max %lu",
  279.             tif->tif_name, (u_long) tile, (u_long) td->td_nstrips);
  280.         return ((tsize_t) -1);
  281.     }
  282.     /*
  283.      * Handle delayed allocation of data buffer.  This
  284.      * permits it to be sized more intelligently (using
  285.      * directory information).
  286.      */
  287.     if ((tif->tif_flags & TIFF_BUFFERSETUP) == 0) {
  288.         if (!TIFFBufferSetup(tif, module))
  289.             return ((tsize_t) -1);
  290.         tif->tif_flags |= TIFF_BUFFERSETUP;
  291.     }
  292.     tif->tif_curtile = tile;
  293.     /* 
  294.      * Compute tiles per row & per column to compute
  295.      * current row and column
  296.      */
  297.     tif->tif_row = (tile % howmany(td->td_imagelength, td->td_tilelength))
  298.         * td->td_tilelength;
  299.     tif->tif_col = (tile % howmany(td->td_imagewidth, td->td_tilewidth))
  300.         * td->td_tilewidth;
  301.  
  302.     tif->tif_flags &= ~TIFF_POSTENCODE;
  303.     if (tif->tif_preencode && !(*tif->tif_preencode)(tif))
  304.         return ((tsize_t) -1);
  305.     /*
  306.      * Clamp write amount to the tile size.  This is mostly
  307.      * done so that callers can pass in some large number
  308.      * (e.g. -1) and have the tile size used instead.
  309.      */
  310.     if ((uint32) cc > tif->tif_tilesize)
  311.         cc = tif->tif_tilesize;
  312.     if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc,
  313.         (tsample_t)(tile/td->td_stripsperimage)))
  314.         return ((tsize_t) 0);
  315.     if (tif->tif_postencode && !(*tif->tif_postencode)(tif))
  316.         return ((tsize_t) -1);
  317.     if (td->td_fillorder != tif->tif_fillorder &&
  318.         (tif->tif_flags & TIFF_NOBITREV) == 0)
  319.         TIFFReverseBits((u_char *)tif->tif_rawdata, tif->tif_rawcc);
  320.     if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
  321.         tif->tif_rawdata, tif->tif_rawcc))
  322.         return ((tsize_t) -1);
  323.     tif->tif_rawcc = 0;
  324.     tif->tif_rawcp = tif->tif_rawdata;
  325.     return (cc);
  326. }
  327.  
  328. /*
  329.  * Write the supplied data to the specified strip.
  330.  * There must be space for the data; we don't check
  331.  * if strips overlap!
  332.  *
  333.  * NB: Image length must be setup before writing; this
  334.  *     interface does not support automatically growing
  335.  *     the image on each write (as TIFFWriteScanline does).
  336.  */
  337. tsize_t
  338. TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
  339. {
  340.     static const char module[] = "TIFFWriteRawTile";
  341.  
  342.     if (!TIFFWriteCheck(tif, 1, module))
  343.         return ((tsize_t) -1);
  344.     if (tile >= tif->tif_dir.td_nstrips) {
  345.         TIFFError(module, "%s: Tile %lu out of range, max %lu",
  346.             tif->tif_name, (u_long) tile,
  347.             (u_long) tif->tif_dir.td_nstrips);
  348.         return ((tsize_t) -1);
  349.     }
  350.     return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ?
  351.         cc : (tsize_t) -1);
  352. }
  353.  
  354. static int
  355. TIFFSetupStrips(TIFF* tif)
  356. {
  357. #define    isUnspecified(td, v) \
  358.     (td->v == (uint32) -1 || (td)->td_imagelength == 0)
  359.     register TIFFDirectory *td = &tif->tif_dir;
  360.  
  361.     if (!isTiled(tif))
  362.         td->td_stripsperimage = isUnspecified(td, td_rowsperstrip) ?
  363.             1 : howmany(td->td_imagelength, td->td_rowsperstrip);
  364.     else
  365.         td->td_stripsperimage = isUnspecified(td, td_tilelength) ?
  366.             1 : TIFFNumberOfTiles(tif);
  367.     td->td_nstrips = td->td_stripsperimage;
  368.     if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
  369.         td->td_nstrips *= td->td_samplesperpixel;
  370.     td->td_stripoffset = (uint32 *)
  371.         _TIFFmalloc(td->td_nstrips * sizeof (uint32));
  372.     td->td_stripbytecount = (uint32 *)
  373.         _TIFFmalloc(td->td_nstrips * sizeof (uint32));
  374.     if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
  375.         return (0);
  376.     /*
  377.      * Place data at the end-of-file
  378.      * (by setting offsets to zero).
  379.      */
  380.     _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32));
  381.     _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32));
  382.     TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
  383.     TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
  384.     return (1);
  385. #undef isUnspecified
  386. }
  387.  
  388. /*
  389.  * Verify file is writable and that the directory
  390.  * information is setup properly.  In doing the latter
  391.  * we also "freeze" the state of the directory so
  392.  * that important information is not changed.
  393.  */
  394. static int
  395. TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
  396. {
  397.     if (tif->tif_mode == O_RDONLY) {
  398.         TIFFError(module, "%s: File not open for writing",
  399.             tif->tif_name);
  400.         return (0);
  401.     }
  402.     if (tiles ^ isTiled(tif)) {
  403.         TIFFError(tif->tif_name, tiles ?
  404.             "Can not write tiles to a stripped image" :
  405.             "Can not write scanlines to a tiled image");
  406.         return (0);
  407.     }
  408.     /*
  409.      * On the first write verify all the required information
  410.      * has been setup and initialize any data structures that
  411.      * had to wait until directory information was set.
  412.      * Note that a lot of our work is assumed to remain valid
  413.      * because we disallow any of the important parameters
  414.      * from changing after we start writing (i.e. once
  415.      * TIFF_BEENWRITING is set, TIFFSetField will only allow
  416.      * the image's length to be changed).
  417.      */
  418.     if ((tif->tif_flags & TIFF_BEENWRITING) == 0) {
  419.         if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
  420.             TIFFError(module,
  421.                 "%s: Must set \"ImageWidth\" before writing data",
  422.                 tif->tif_name);
  423.             return (0);
  424.         }
  425.         if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
  426.             TIFFError(module,
  427.             "%s: Must set \"PlanarConfiguration\" before writing data",
  428.                 tif->tif_name);
  429.             return (0);
  430.         }
  431.         if (tif->tif_dir.td_stripoffset == NULL &&
  432.             !TIFFSetupStrips(tif)) {
  433.             tif->tif_dir.td_nstrips = 0;
  434.             TIFFError(module, "%s: No space for %s arrays",
  435.                 tif->tif_name, isTiled(tif) ? "tile" : "strip");
  436.             return (0);
  437.         }
  438.         tif->tif_flags |= TIFF_BEENWRITING;
  439.     }
  440.     return (1);
  441. }
  442.  
  443. /*
  444.  * Setup the raw data buffer used for encoding.
  445.  */
  446. static int
  447. TIFFBufferSetup(TIFF* tif, const char* module)
  448. {
  449.     tsize_t size;
  450.  
  451.     if (isTiled(tif))
  452.         tif->tif_tilesize = size = TIFFTileSize(tif);
  453.     else
  454.         tif->tif_scanlinesize = size = TIFFScanlineSize(tif);
  455.     /*
  456.      * Make raw data buffer at least 8K
  457.      */
  458.     if (size < 8*1024)
  459.         size = 8*1024;
  460.     tif->tif_rawdata = (tidata_t)_TIFFmalloc(size);
  461.     if (tif->tif_rawdata == NULL) {
  462.         TIFFError(module, "%s: No space for output buffer",
  463.             tif->tif_name);
  464.         return (0);
  465.     }
  466.     tif->tif_flags |= TIFF_MYBUFFER;
  467.     tif->tif_rawdatasize = size;
  468.     tif->tif_rawcc = 0;
  469.     tif->tif_rawcp = tif->tif_rawdata;
  470.     return (1);
  471. }
  472.  
  473. /*
  474.  * Grow the strip data structures by delta strips.
  475.  */
  476. static int
  477. TIFFGrowStrips(TIFF* tif, int delta, const char* module)
  478. {
  479.     TIFFDirectory *td = &tif->tif_dir;
  480.  
  481.     assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
  482.     td->td_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset,
  483.         (td->td_nstrips + delta) * sizeof (uint32));
  484.     td->td_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount,
  485.         (td->td_nstrips + delta) * sizeof (uint32));
  486.     if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) {
  487.         td->td_nstrips = 0;
  488.         TIFFError(module, "%s: No space to expand strip arrays",
  489.             tif->tif_name);
  490.         return (0);
  491.     }
  492.     _TIFFmemset(td->td_stripoffset+td->td_nstrips, 0, delta*sizeof (uint32));
  493.     _TIFFmemset(td->td_stripbytecount+td->td_nstrips, 0, delta*sizeof (uint32));
  494.     td->td_nstrips += delta;
  495.     return (1);
  496. }
  497.  
  498. /*
  499.  * Append the data to the specified strip.
  500.  *
  501.  * NB: We don't check that there's space in the
  502.  *     file (i.e. that strips do not overlap).
  503.  */
  504. static int
  505. TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
  506. {
  507.     TIFFDirectory *td = &tif->tif_dir;
  508.     static const char module[] = "TIFFAppendToStrip";
  509.  
  510.     if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
  511.         /*
  512.          * No current offset, set the current strip.
  513.          */
  514.         if (td->td_stripoffset[strip] != 0) {
  515.             if (!SeekOK(tif, td->td_stripoffset[strip])) {
  516.                 TIFFError(module,
  517.                     "%s: Seek error at scanline %lu",
  518.                     tif->tif_name, (u_long) tif->tif_row);
  519.                 return (0);
  520.             }
  521.         } else
  522.             td->td_stripoffset[strip] =
  523.                 TIFFSeekFile(tif, (toff_t) 0, L_XTND);
  524.         tif->tif_curoff = td->td_stripoffset[strip];
  525.     }
  526.     if (!WriteOK(tif, data, cc)) {
  527.         TIFFError(module, "%s: Write error at scanline %lu",
  528.             tif->tif_name, (u_long) tif->tif_row);
  529.         return (0);
  530.     }
  531.     tif->tif_curoff += cc;
  532.     td->td_stripbytecount[strip] += cc;
  533.     return (1);
  534. }
  535.  
  536. /*
  537.  * Internal version of TIFFFlushData that can be
  538.  * called by ``encodestrip routines'' w/o concern
  539.  * for infinite recursion.
  540.  */
  541. int
  542. TIFFFlushData1(TIFF* tif)
  543. {
  544.     if (tif->tif_rawcc > 0) {
  545.         if (tif->tif_dir.td_fillorder != tif->tif_fillorder &&
  546.             (tif->tif_flags & TIFF_NOBITREV) == 0)
  547.             TIFFReverseBits((u_char *)tif->tif_rawdata,
  548.                 tif->tif_rawcc);
  549.         if (!TIFFAppendToStrip(tif,
  550.             isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
  551.             tif->tif_rawdata, tif->tif_rawcc))
  552.             return (0);
  553.         tif->tif_rawcc = 0;
  554.         tif->tif_rawcp = tif->tif_rawdata;
  555.     }
  556.     return (1);
  557. }
  558.  
  559. /*
  560.  * Set the current write offset.  This should only be
  561.  * used to set the offset to a known previous location
  562.  * (very carefully), or to 0 so that the next write gets
  563.  * appended to the end of the file.
  564.  */
  565. void
  566. TIFFSetWriteOffset(TIFF* tif, toff_t off)
  567. {
  568.     tif->tif_curoff = off;
  569. }
  570.